#include "dma.h"

//由main函数调用一次
void dma_uart_rx_init(void)
{
    dma_single_data_parameter_struct dma_init_struct;		
	//DMA外设时钟使能
	rcu_periph_clock_enable(RCU_DMA0);								//时钟使能
	rcu_periph_clock_enable(RCU_DMA1);								//时钟使能
    dma_deinit(DMA0, DMA_CH1);										//复位DMA通道
	dma_deinit(DMA0, DMA_CH2);										//复位DMA通道
	dma_deinit(DMA0, DMA_CH5);										//复位DMA通道
	dma_deinit(DMA1, DMA_CH7);										//复位DMA通道
	//串口接收公共部分
	dma_init_struct.direction 	= DMA_PERIPH_TO_MEMORY;				//外设到内存
	dma_init_struct.memory_inc 	= DMA_MEMORY_INCREASE_ENABLE;		//内存地址递增
	dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;	//外设数据位长度
	dma_init_struct.number 		= UART_RX_BUFLEN;					//传输数量
	dma_init_struct.periph_inc 	= DMA_PERIPH_INCREASE_DISABLE;		//外设地址不递增
	dma_init_struct.priority 	= DMA_PRIORITY_HIGH;				//高优先级
	//4个串口
	dma_init_struct.memory0_addr= (uint32_t)mUart[0].rxbuf;			//内存地址
	dma_init_struct.periph_addr	= USART0+4 ;						//外设地址
	dma_single_data_mode_init(DMA1, DMA_CH2, dma_init_struct);		//初始化为仅数据模式
	dma_circulation_enable(DMA1, DMA_CH2);							//启用DMA循环模式	这句必须放在初始化之后，否则会导致DMA异常
	dma_channel_subperipheral_select(DMA1, DMA_CH2, DMA_SUBPERI4);	//DMA通道外设选择   	串口0-4收发都是4
	
	dma_init_struct.memory0_addr= (uint32_t)mUart[1].rxbuf;			//内存地址
	dma_init_struct.periph_addr	= USART1+4 ;						//外设地址
	dma_single_data_mode_init(DMA0, DMA_CH5, dma_init_struct);		//初始化为仅数据模式
	dma_circulation_enable(DMA0, DMA_CH5);							//启用DMA循环模式
	dma_channel_subperipheral_select(DMA0, DMA_CH5, DMA_SUBPERI4);	//DMA通道外设选择
	
	dma_init_struct.memory0_addr= (uint32_t)mUart[2].rxbuf;			//内存地址
	dma_init_struct.periph_addr	= USART2+4 ;						//外设地址
	dma_single_data_mode_init(DMA0, DMA_CH1, dma_init_struct);		//初始化为仅数据模式
	dma_circulation_enable(DMA0, DMA_CH1);							//启用DMA循环模式
	dma_channel_subperipheral_select(DMA0, DMA_CH1, DMA_SUBPERI4);	//DMA通道外设选择
	
	dma_init_struct.memory0_addr= (uint32_t)mUart[3].rxbuf;			//内存地址
	dma_init_struct.periph_addr	= UART3+4 ;							//外设地址
	dma_single_data_mode_init(DMA0, DMA_CH2, dma_init_struct);		//初始化为仅数据模式
	dma_circulation_enable(DMA0, DMA_CH2);							//启用DMA循环模式
	dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI4);	//DMA通道外设选择
	//使能各通道 开始工作
	dma_channel_enable(DMA0, DMA_CH1);
    dma_channel_enable(DMA0, DMA_CH2);
	dma_channel_enable(DMA0, DMA_CH5);
    dma_channel_enable(DMA1, DMA_CH2);
	//发送相关 中断允许
	nvic_irq_enable(DMA0_Channel3_IRQn, 2, 1);						//打开DMA中断，设置中断优先级
	nvic_irq_enable(DMA0_Channel4_IRQn, 2, 1);						//打开DMA中断，设置中断优先级
	nvic_irq_enable(DMA0_Channel6_IRQn, 2, 1);						//打开DMA中断，设置中断优先级
	nvic_irq_enable(DMA1_Channel7_IRQn, 2, 1);						//打开DMA中断，设置中断优先级
}
/*
由串口发送队列调用
n：串口号 0-3
*/
void dma_uart_tx(u8 n,u16 len)
{
	dma_single_data_parameter_struct dma_init_struct;
	
	dma_init_struct.direction 	= DMA_MEMORY_TO_PERIPH;				//外设到内存
	dma_init_struct.memory_inc 	= DMA_MEMORY_INCREASE_ENABLE;		//内存地址递增
	dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;	//外设数据位长度
	dma_init_struct.number 		= len;								//传输数量
	dma_init_struct.periph_inc 	= DMA_PERIPH_INCREASE_DISABLE;		//外设地址不递增
	dma_init_struct.priority 	= DMA_PRIORITY_HIGH;				//高优先级
	switch(n){
		case 0:{
			dma_deinit(DMA1, DMA_CH7);										//复位DMA通道
			dma_init_struct.memory0_addr= (uint32_t)mUart[0].txdata;		//内存地址
			dma_init_struct.periph_addr	= USART0+4 ;						//外设地址
			dma_circulation_enable(DMA1, DMA_CH7);							//禁用DMA循环模式
			dma_single_data_mode_init(DMA1, DMA_CH7, dma_init_struct);		//初始化为仅数据模式
			dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4);	//DMA通道外设选择   串口0-4收发都是4
			dma_interrupt_enable(DMA1, DMA_CH7,DMA_CHXCTL_FTFIE);			//DMA传输完成中断
			dma_channel_enable(DMA1, DMA_CH7);								//开始传输
		}break;
		case 1:{
			dma_deinit(DMA0, DMA_CH6);										//复位DMA通道
			dma_init_struct.memory0_addr= (uint32_t)mUart[1].txdata;		//内存地址
			dma_init_struct.periph_addr	= USART1+4 ;						//外设地址
			dma_circulation_enable(DMA0, DMA_CH6);							//禁用DMA循环模式
			dma_single_data_mode_init(DMA0, DMA_CH6, dma_init_struct);		//初始化为仅数据模式
			dma_channel_subperipheral_select(DMA0, DMA_CH6, DMA_SUBPERI4);	//DMA通道外设选择   串口0-4收发都是4
			dma_interrupt_enable(DMA0, DMA_CH6,DMA_CHXCTL_FTFIE);			//DMA传输完成中断
			dma_channel_enable(DMA0, DMA_CH6);								//开始传输
		}break;
		case 2:{
			dma_deinit(DMA0, DMA_CH3);										//复位DMA通道
			dma_init_struct.memory0_addr= (uint32_t)mUart[2].txdata;		//内存地址
			dma_init_struct.periph_addr	= USART2+4 ;						//外设地址
			dma_circulation_enable(DMA0, DMA_CH3);							//禁用DMA循环模式
			dma_single_data_mode_init(DMA0, DMA_CH3, dma_init_struct);		//初始化为仅数据模式
			dma_channel_subperipheral_select(DMA0, DMA_CH3, DMA_SUBPERI4);	//DMA通道外设选择   串口0-4收发都是4
			dma_interrupt_enable(DMA0, DMA_CH3,DMA_CHXCTL_FTFIE);			//DMA传输完成中断
			dma_channel_enable(DMA0, DMA_CH3);								//开始传输
		}break;
		case 3:{
			dma_deinit(DMA0, DMA_CH4);										//复位DMA通道
			dma_init_struct.memory0_addr= (uint32_t)mUart[3].txdata;		//内存地址
			dma_init_struct.periph_addr	= UART3+4 ;							//外设地址
			dma_circulation_enable(DMA0, DMA_CH4);							//禁用DMA循环模式
			dma_single_data_mode_init(DMA0, DMA_CH4, dma_init_struct);		//初始化为仅数据模式
			dma_channel_subperipheral_select(DMA0, DMA_CH4, DMA_SUBPERI4);	//DMA通道外设选择   串口0-4收发都是4
			dma_interrupt_enable(DMA0, DMA_CH4,DMA_CHXCTL_FTFIE);			//DMA传输完成中断
			dma_channel_enable(DMA0, DMA_CH4);								//开始传输
		}break;
		default:{
		}break;
	}
}

